package main

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"wx_spider_go/config"
	"wx_spider_go/logger"
	"wx_spider_go/models"
	"wx_spider_go/script"

	"github.com/go-redis/redis/v8"
)

func main() {
	// 初始化日志系统
	logger.InitLogger()
	logger.Info("微信公众号文章采集器启动中...")

	rdb := redis.NewClient(&redis.Options{
		Addr:         fmt.Sprintf("%s:%d", config.GlobalConfig.Redis.Host, config.GlobalConfig.Redis.Port),
		Password:     config.GlobalConfig.Redis.Password,
		DB:           config.GlobalConfig.Redis.DB,
		PoolSize:     config.GlobalConfig.Redis.PoolSize,
		MinIdleConns: config.GlobalConfig.Redis.MinIdleConns,
	})
	_, err := rdb.Ping(context.Background()).Result()
	if err != nil {
		logger.Error("Redis 连接失败: %v", err)
		panic(err)
	}
	logger.Success("Redis 连接成功")
	for {
		// 获取所有公众号配置
		configKeys, err := rdb.Keys(context.Background(), "wx_caiji:*:config").Result()
		if err != nil {
			logger.Error("获取公众号配置失败: %v", err)
			return
		}
		logger.StatsInfo("发现公众号配置数量: %d", len(configKeys))

		for index, configKey := range configKeys {
			// 获取配置
			configJSON, err := rdb.Get(context.Background(), configKey).Result()
			if err != nil {
				logger.Error("获取配置 %s 失败: %v", configKey, err)
				continue
			}
			var spiderConfig models.Config
			err = json.Unmarshal([]byte(configJSON), &spiderConfig)
			if err != nil {
				logger.Error("解析配置失败: %v", err)
				continue
			}

			name := spiderConfig.Name
			isOnce := spiderConfig.Once

			// 设置当前公众号名称到日志上下文
			logger.SetGzhName(fmt.Sprintf("[%d]-[%s]", index, name))

			if spiderConfig.MinioEndpoint == "" {
				spiderConfig.MinioEndpoint = config.GlobalConfig.MinIO.Endpoint
			}
			if isOnce {
				logger.Processing("开始一次性采集所有文章")
				articleKey := fmt.Sprintf("wx_caiji:%s:article_list", name)

				for {
					articleJSON, err := rdb.LPop(context.Background(), articleKey).Result()
					if err != nil {
						if errors.Is(err, redis.Nil) {
							break
						}
						logger.Error("获取文章失败: %v", err)
						break
					}

					var article models.Article
					err = json.Unmarshal([]byte(articleJSON), &article)
					if err != nil {
						logger.Error("解析文章失败: %v", err)
						continue
					}

					err = script.HandlerArticle(article, spiderConfig)
					if err != nil {
						logger.Error("处理文章失败: %v", err)
					}
				}

				// 清除公众号名称上下文
				logger.SetGzhName("")
			} else {
				// 查找最近一天的文章
				articleKey := fmt.Sprintf("wx_caiji:%s:list", name)
				now := time.Now()
				yesterday := now.AddDate(0, 0, -1)
				articleIDs, err := rdb.ZRangeByScore(context.Background(), articleKey, &redis.ZRangeBy{
					Min: fmt.Sprint(yesterday.Unix()),
					Max: fmt.Sprint(now.Unix()),
				}).Result()

				if err != nil {
					logger.Error("获取文章列表失败: %v", err)
					printBreakSpace()
					continue
				}
				if len(articleIDs) == 0 {
					logger.Warn("最近一天无新文章，跳过")
					printBreakSpace()
					continue
				}
				logger.StatsInfo("最近一天文章数量：%d", len(articleIDs))

				for _, articleID := range articleIDs {
					articleKey2 := fmt.Sprintf("wx_caiji:%s:article:%s", name, articleID)
					articleJSON, err := rdb.Get(context.Background(), articleKey2).Result()
					if err != nil {
						logger.Error("获取文章详情失败: %v", err)
						continue
					}
					var article models.Article
					err = json.Unmarshal([]byte(articleJSON), &article)
					if err != nil {
						logger.Error("解析文章失败: %v", err)
						continue
					}
					err = script.HandlerArticle(article, spiderConfig)
					if err != nil {
						logger.Error("处理文章失败: %v", err)
					}
				}
			}
			printBreakSpace()
			time.Sleep(time.Second * 5)
		}
	}

}
func printBreakSpace() {
	fmt.Println()
	fmt.Println()
}
